<template>
  <el-table-column v-bind="$attrs" :label="label" :width="width">
    <!-- 头部 -->
    <template #header="{ row, $index }" slot="header" slot-scope="scope">
      <slot name="header" :column="row" :$index="$index">
        {{ label }}
      </slot>
    </template>
    <template #default="{ row, $index }">
      <!-- 预览部分 -->
      <div v-show="!row.isEdit || editDisable">
        <slot name="preview" :row="row" :$index="$index">
          {{ previewText(row) }}
        </slot>
      </div>

      <!-- 编辑部分 -->
      <div
        v-show="row.isEdit && !editDisable"
        :class="{ 'bg-white': ['input', 'select', 'date'].includes(state) }"
      >
        <slot name="edit" :row="row" :$index="$index">
          <el-input
            v-if="state === 'input' && type === 'text'"
            v-model.trim="row[prop]"
            v-bind="$attrs"
            :cust-id="prop + '-' + $index + '-' + getParentUid()"
            :placeholder="placeholderComp"
            :type="type"
            @input="numberInput($event, $index)"
          />

          <el-input
            v-if="state === 'input' && type === 'number'"
            v-model.number="row[prop]"
            v-bind="$attrs"
            :cust-id="prop + '-' + $index + '-' + getParentUid()"
            :placeholder="placeholderComp"
            :type="type"
          />
          <el-select
            v-if="state === 'select'"
            v-model="row[prop]"
            clearable
            filterable
            :placeholder="placeholderComp"
            v-bind="$attrs"
            @change="selectChange($event, $index)"
          >
            <el-option
              v-for="item in selectOption.options"
              :key="item[selectOption.label]"
              :label="item[selectOption.label]"
              :value="item[selectOption.value]"
            />
          </el-select>
          <el-switch v-if="state === 'switch'" v-model="row[prop]" v-bind="$attrs" />
          <el-radio-group v-if="state === 'radio'" v-model="row[prop]" v-bind="$attrs">
            <el-radio
              v-for="(item, index) in radioOption.options"
              :key="item[radioOption.label]"
              :label="item[radioOption.value]"
            >
              {{ item[radioOption.label] }}
            </el-radio>
          </el-radio-group>
          <el-date-picker
            v-if="state === 'date'"
            v-model="row[prop]"
            v-bind="$attrs"
            type="date"
            value-format="YYYY-MM-DD"
            :placeholder="placeholderComp"
          />
        </slot>
      </div>
    </template>
  </el-table-column>
</template>

<script lang="ts" setup name="LtTableColumnEdit">
  import {
    computed,
    reactive,
    watch,
    useAttrs,
    ComputedRef,
    getCurrentInstance,
    PropType
  } from 'vue'
  import { SelectOption, RadioOption, SwitchOption } from '../lt-table-column-operation/index.d'
  const props = defineProps({
    prop: {
      type: String,
      default: '',
      required: true
    },
    label: {
      type: String,
      default: '',
      required: true
    },
    placeholder: {
      type: String,
      default: ''
    },
    // 禁用编辑项
    editDisable: {
      type: Boolean,
      default: false
    },
    // 编辑项的类型
    state: {
      type: String,
      default: 'input',
      validator: value => {
        // 这个值必须匹配下列字符串中的一个
        return ['input', 'select', 'radio', 'switch', 'date'].includes(value as string)
      }
    },
    // el-select的配置参数
    selectOpt: {
      type: Object as PropType<SelectOption>,
      default: () => ({})
    },
    // el-radio的配置参数
    radioOpt: {
      type: Object as PropType<RadioOption>,
      default: () => ({})
    },
    // el-switch的配置参数
    SwitchOption: {
      type: Object as PropType<SwitchOption>,
      default: () => ({})
    },
    type: {
      type: String,
      default: 'text'
    },
    width: {
      type: String,
      default: ''
    }
  })

  const attrs = useAttrs()
  const emit = defineEmits(['change', 'input'])

  // el-select的配置参数
  const selectOption = reactive<SelectOption>({
    previewLabel: '', // 用于回显
    options: [], // el-select的选项
    label: 'label',
    value: 'value'
  })

  // el-radio的配置参数
  let radioOption = reactive({
    previewLabel: '', // 用于回显
    options: [],
    label: 'label',
    value: 'value'
  })
  // el-switch的配置参数
  let switchOption = reactive({
    openText: '启用', // 开启状态下预览的文字
    closeText: '停用' // 关闭状态下预览的文字
  })

  const placeholderComp: ComputedRef<string> = computed(() => {
    return props.placeholder
      ? props.placeholder
      : `请${props.state === 'input' ? '输入' : '选择'}${props.label}`
  })

  // 数据监听
  watch(
    () => props.selectOpt,
    () => {
      /**
       * 这个地方有问题
       * 1. ts的报错
       * 2. 扩展运算符合并的时候,数组失去了响应性
       */
      for (const key in props.selectOpt) {
        if (key in selectOption) {
          selectOption[key] = props.selectOpt[key]
        }
      }
      if (!selectOption.options) selectOption.options.length = []
    },
    {
      immediate: true,
      deep: true
    }
  )

  watch(
    () => props.radioOpt,
    () => {
      radioOption = { ...radioOption, ...props.radioOpt }
    },
    {
      immediate: true,
      deep: true
    }
  )

  watch(
    () => props.SwitchOption,
    () => {
      switchOption = { ...switchOption, ...props.SwitchOption }
    },
    {
      immediate: true,
      deep: true
    }
  )

  /**
   * 预览显示的文字
   * @param {Object} row
   */
  const previewText = (row: any) => {
    // el-select时的预览
    if (props.state === 'select' && row[props.prop]) {
      /**
       * 优先根据value去数组查找并取值,取不到则取label,若都为空则返回空
       */
      const options = selectOption.options
      let result = []
      if (options.length)
        result = options.filter((item: any) => item[selectOption.value!] === row[props.prop])

      return result.length ? result[0][selectOption.label!] : row[selectOption.previewLabel!] || ''
    }
    // el-radio时的预览
    if (props.state === 'radio') {
      const options: any = radioOption.options
      let result = []
      if (options.length)
        result = options.filter((item: any) => item[radioOption.value] === row[props.prop])
      return result.length ? result[0][radioOption.label] : row[radioOption.previewLabel] || ''
    }

    // el-switch时的预览
    if (props.state === 'switch') {
      return row[props.prop] === (attrs['active-value'] || true)
        ? switchOption.openText
        : switchOption.closeText
    }

    return row[props.prop]
  }

  const selectChange = (e: Event, index: number) => {
    emit('change', {
      data: selectOption.options.filter((item: any) => item[selectOption.value!] === e)[0],
      index
    })
  }

  const numberInput = (e: Event, index: number) => {
    emit('input', { data: e, index })
  }

  const getParentUid = () => {
    const currentExample = getCurrentInstance()
    return currentExample?.parent?.uid
  }

  defineExpose({
    selectOption
  })
</script>

<style scoped>
  .bg-white {
    background-color: #ffffff !important;
    border-radius: 10px;
  }
  /* el-radio的样式修改 */
  :deep(.el-radio) {
    margin-right: 10px;
  }
  :deep(.el-radio__label) {
    font-size: 13px;
  }

  /* :deep(.el-input__suffix) {
    height: 23px;
    line-height: 23px;
    align-items: center;
    justify-content: center;
    display: flex;
  } */
  :deep(th .cell) {
    color: #364760 !important;
  }
  :deep(.el-input__wrapper) {
    box-shadow: none !important;
  }

  /* el-input样式修改 */
  :deep(.el-input__inner) {
    height: 23px !important;
    line-height: 23px !important;
    font-size: 13px;
    width: 100% !important;
    border: none;
    color: black;
    font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei',
      '\5FAE\8F6F\96C5\9ED1', Arial, sans-serif !important;
    box-shadow: none;
  }

  /* el-input选中时的聚焦 */
  :deep(.el-input__inner:hover) {
    box-shadow: none;
  }
  :deep(.el-input__inner:focus) {
    box-shadow: none;
  }

  /* el-select的样式修改 */
  :deep(.el-select) {
    width: 100%;
  }

  /* el-select 选中时的聚焦 */
  :deep(.el-select .el-input.is-focus .el-input__wrapper) {
    box-shadow: none !important;
  }
  :deep(.el-select .el-input__wrapper.is-focus) {
    box-shadow: none !important;
  }

  /* 日期选择器 */
  :deep(.el-date-editor) {
    width: 100%;
    height: 23px;
    line-height: 23px;
  }
  :deep(.el-date-editor .el-input__inner) {
    padding-left: 0 !important;
  }

  /* 去掉 input number自带的调整上下的角标 */
  :deep(.el-input input[type='number']::-webkit-outer-spin-button) {
    margin: 0;
    -webkit-appearance: none !important;
  }
  :deep(.el-input input[type='number']::-webkit-inner-spin-button) {
    margin: 0;
    -webkit-appearance: none !important;
  }
  :deep(.el-input) {
    -moz-appearance: textfield;
  }

  /* el-switch 样式修改 */
  :deep(.el-switch) {
    height: 23px;
    line-height: 23px;
  }
  /* 日期选择器前面的图标 */
  /* /deep/ .el-date-editor .el-input__prefix{
    top: -9px;
  }
  */
</style>
